/* MC202 - Estruturas de dados - 2. semestre de 2005.
 * Fun�es para a compress� e descompress� de arquivos. */

#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include "huffman.h"


/* Voc�deve implementar todas as fun�es abaixo. Se necess�io,
 * voc�pode criar fun�es auxiliares aqui. */
void parv(No *arv, int level){   int i;    if (arv != NULL){          parv(arv->esq, level+1);          for(i=0;i<level;i++){       printf("       .");     }      printf("(%d,%d)\n",arv->c,arv->freq );          parv(arv->dir, level+1);    }}
void in(No *a){
  if(!a){return;}
  in(a->esq);
  printf("[%d %d]",a->c,a->freq);
  in(a->dir);
  return;
}
void pre(No *a){
  if(!a){return;}
  printf("(%d %d)",a->c,a->freq);
  pre(a->esq);
  pre(a->dir);
  return;
}
void codif(FILE *arq,char ** tab) {
  int c;
  c=getc(arq);
  while((c>=0)&&(arq)){
    printf("%s",tab[c]);
    if(feof(arq)){break;}
    c=getc(arq);
  }
  fclose(arq);
  return;
}
void compr(FILE *arq,char ** tab) {
  int c,t;
  int a=0,b=0;
  c=getc(arq);
  while((c>=0)&&(arq)){
    t=0;
    while((tab[c][t]==48)||(tab[c][t]==49)){
      a<<=1;
      a=a+(tab[c][t]-48);
      b++;
      if(b==8){
	fwrite(&a,1,1,stdout);
	a=0;
	b=0;
      }
      t++;
    }
    if(feof(arq)){break;}
    c=getc(arq);
  }
  if(b){
    while(b!=8){
      a<<=1;
      b++;
    }
    fwrite(&a,1,1,stdout);
  }
  fclose(arq);
  return;
}
/* Imprime a tabela de codifica�o do arquivo. */
void imprime_tabela_arquivo(char *nomearq) {
  char ** tab;
  No * arv;
  arv=gera_arvore_arquivo(nomearq);
//   in(arv);
//   printf("\n");
//   pre(arv);
//   printf("\n");
  tab=gera_tabela_arvore(arv);
  destroi_arvore(arv);
  imprime_tabela(tab);
  destroi_tabela(tab);
}


/* Codifica (formato texto) o arquivo e imprime. */
void codifica_arquivo(char *nomearq) {
  char ** tab;
  No * arv;
  arv=gera_arvore_arquivo(nomearq);
//   in(arv);
//   printf("\n");
//   pre(arv);
//   printf("\n");
  tab=gera_tabela_arvore(arv);
  imprime_tabela(tab);
  printf("%d\nT\n",arv->freq);
  codif(fopen(nomearq,"r"),tab);
  destroi_arvore(arv);
  destroi_tabela(tab);
}


/* Compacta (formato bin�io) o arquivo e imprime. */
void compacta_arquivo(char *nomearq) {
  char ** tab;
  No * arv;
  arv=gera_arvore_arquivo(nomearq);
//   parv(arv,0);
  tab=gera_tabela_arvore(arv);
  imprime_tabela(tab);
  printf("%d\nB\n",arv->freq);
  compr(fopen(nomearq,"r"),tab);
  destroi_arvore(arv);
  destroi_tabela(tab);
}


/* Descomprime o arquivo e imprime. */
void descomprime_arquivo(char *nomearq) {
  int l,c=0;
  int aux;
  char * ax;
  char op;
  No * arv;
  No * and;
  FILE * arq = fopen(nomearq,"r");
  char ** tab;
  tab=calloc(N_CHARS,sizeof(void*));
  arv=calloc(1,sizeof(No));
  fscanf(arq,"%d\n",&l);
  while(c<l){
    ax=calloc(100,sizeof(char));
    fscanf(arq,"%d %s\n",&aux,ax);
    tab[aux]=ax;
    c++;
  }
  c=0;
  while(c<N_CHARS){
    if(tab[c]){
      insere_arvore(arv,c,tab[c]);
    }
    c++;
  }
  destroi_tabela(tab);
  fscanf(arq,"%d\n%c\n",&l,&op);
//   parv(arv,0);
  if(op=='T'){
    c=0;
    and=arv;
    while(c<l){
      op=getc(arq);
      if(op==48){
        and=and->esq;
      }else if(op==49){
        and=and->dir;
      }
      if(and->c){
        printf("%c",and->c);
        and=arv;
	c++;
      }
    }
  }else if(op=='B'){
    int c2=0;
    int bit;
    c=0;
    and=arv;
    while(c<l){
      fread(&aux,1,1,arq);
      c2=0;
      while(c2<8){
	bit=(aux&128)>>7;
	aux<<=1;
	c2++;
        if(bit==0){
	 and=and->esq;
        }else if(bit==1){
	 and=and->dir;
        }
        if(and->c){
	   printf("%c",and->c);
	   and=arv;
	   c++;
	   if(c==l){break;}
        }
      }
      if(feof(arq)){break;}
    }
  }
  destroi_arvore(arv);
  fclose(arq);
}

/*BBE foi utilizado nesse programa*/
